package com.queue;

/**
 * @Author: linKe
 * @Date: 2022/1/1 21:43
 * @FileName: SeqQueue
 * @version: 1.0
 * @Description: 顺序循环队列实现类
 */
public final  class SeqQueue<T> implements Queue<T> {
    /**
     * 存储队列数据元素的数组
     */
    private Object[] element;
    /**
     * 队列 头尾 下标
     * front,rear 分别为队列头尾下标
     */
    private int front, rear;
    /**
     * 设置最小容量   常量值
     */
    private final int MIXCapacity = 64;

    /**
     * 构造默认容量的空队列
     */
    public SeqQueue() {
        this(64);
    }

    /**
     * 构造长度为 capacity 的 空队列
     *
     * @param capacity 长度值
     */
    public SeqQueue(int capacity) {
        if (capacity < MIXCapacity) {
            //设置数组容量去最小值
            capacity = 64;
        }
        this.element = new Object[capacity];
        //设置空队列
        this.front = this.rear = 0;
    }

    /**
     * 判断队列是否为空，若空返回true
     *
     * @return 结果
     */
    @Override
    public boolean isEmpty() {
        //比较头尾指针的值是否一致
        return this.front == this.rear;
    }

    /**
     * 元素x入队，空对象不能入队
     *
     * @param x 元素值x
     * @return 结果
     */
    @Override
    public boolean add(T x) {
        if (x == null) {
            return false;
            //抛出空对象异常
            //throw new NullPointerException("x==null");
        }
        if (this.front == (this.rear + 1) % this.element.length) {
            Object[] temp = this.element;
            this.element = new Object[temp.length * 2];
            int j = 0;
            //i != this.rear 头指针不等于尾指针  (i + 1) % temp.length 头指针模以数组长度
            for (int i = this.front; i != this.rear; i = (i + 1) % temp.length) {
                //按照队列元素次序赋值数组元素
                this.element[j++] = temp[i];
            }
            //重置头尾指针位置
            this.front = 0;
            this.rear = j;
        }
        // 新增的元素值 赋给尾指针
        this.element[this.rear] = x;
        //尾指针的顺序移位
        this.rear = (this.rear + 1) % this.element.length;
        //
        return true;
    }

    /**
     * 返回队头元素，没有删除。
     * 若队列空，则返回null。
     *
     * @return 结果
     */
    @Override
    public T peek() {
        return this.isEmpty() ? null : (T) this.element[this.front];
    }

    /**
     * 返回队尾元素，没有删除。
     * 若队列空，则返回null。
     *
     * @return 结果
     */
    public T rear() {
        //这个判断只是判断 队列现有容量的最后一位的值    实际的数据无用
        return this.isEmpty() ? null : (T) this.element[this.element.length-1];
    }

    /**
     * 出队，返回队头元素，若队列空返回null
     *
     * @return 结果
     */
    @Override
    public T poll() {
        if (this.isEmpty()) {
            return null;
        }
        //临时变量接收 队头的元素
        T temp = (T) this.element[this.front];
        //头指针向后移位
        this.front = (this.front + 1) % this.element.length;
        return temp;
    }

    /**
     * 重写toString
     * 返回队列所有元素的描写字符串，形式为“（，）”，按照队列元素次序
     *
     * @return 结果
     */
    @Override
    public String toString() {
        StringBuilder stringBuffer = new StringBuilder(this.getClass().getName() + "(");
        //i=(i+1)%this.element.length 以模的方式取值
        for (int i = this.front; i != this.rear; i = (i + 1) % this.element.length) {
            //按照队列次序复制数组元素
            //stringBuffer.append(this.element[i].toString() + ",");
            //字符串追加更改为用api方法
            stringBuffer.append(this.element[i].toString()).append( ",");

        }
        //将串最后多余的一个字符","改为“）”
        stringBuffer.setCharAt(stringBuffer.length() - 1, ')');

        return new String(stringBuffer);
    }
}
